package read

import (
	"bufio"
	"io"
	"io/fs"
	"os"
	"path/filepath"
	"playbook/ginsvr/src/global"
	"playbook/ginsvr/src/orm"
	"playbook/ginsvr/src/orm/dict"
	"playbook/ginsvr/src/utils/stringutil"
	"playbook/ginsvr/src/utils/uuidutil"
	"regexp"
	"strings"

	"github.com/sirupsen/logrus"
)

var (
	resultJavaList []string
	resultJsonList []string
	params         []orm.Parameter
	paramMap       map[string]string
	asvs           []orm.Service
	asvMap         map[string]orm.Service
	activities     []orm.AtomSvrDefine
	activityMap    map[string]orm.AtomSvrDefine
	paramRelas     []orm.Paramrelation
	paramRelaMap   map[string]orm.Paramrelation
	updParams      []*map[string]interface{}
	pprelaMap      map[string]*map[string]interface{}
)

//遍历文件的回调函数
func walkFunc(path string, info fs.FileInfo, err error) error {
	if info.IsDir() {
		return nil
	}

	if matchjava := strings.Contains(path, ".java"); matchjava {
		resultJavaList = append(resultJavaList, path)
	}

	if matchjson := strings.Contains(path, ".json"); matchjson {
		resultJsonList = append(resultJsonList, path)
	}

	return nil
}

//判断文件的一行内容是否一个类定义的一部分或全部
func isclassdef(source string, isclsbegined bool) (isclsbegin bool, isclsend bool) {
	isclsbegin = isclsbegined
	isclsend = false

	regclsbegin := regexp.MustCompile(`^\s*public\s+class`)
	if regclsbegin == nil {
		global.LOG.Errorln("regexp regclsbegin err")
		return false, false
	}

	if regclsbegin.MatchString(source) {
		isclsbegin = true
	}
	if strings.Contains(source, "{") && isclsbegin {
		isclsend = true
	}

	return isclsbegin, isclsend
}

//判断文件的一行内容是否一个执行方法的一部分或全部
func isexecdef(source string, isclsbegined bool) (isclsbegin bool, isclsend bool) {
	isclsbegin = isclsbegined
	isclsend = false

	regclsbegin := regexp.MustCompile(`^\s+public\s+.+\s+doAtom`)
	if regclsbegin == nil {
		global.LOG.Errorln("regexp regclsbegin err")
		return false, false
	}

	if regclsbegin.MatchString(source) {
		isclsbegin = true
	}
	if strings.Contains(source, "{") && isclsbegin {
		isclsend = true
	}

	return isclsbegin, isclsend
}

//判断文件的一行内容是否一个参数定义的一部分或全部
func isparamdef(source string, isparambegined bool) (isparambegin bool, isparamend bool) {
	isparambegin = isparambegined
	isparamend = false

	regparambegin := regexp.MustCompile(`^\s+private.+`)
	if regparambegin == nil {
		global.LOG.Errorln("regexp regclsbegin err")
		return false, false
	}

	if regparambegin.MatchString(source) && !(strings.Contains(source, "(") || strings.Contains(source, ")")) {
		isparambegin = true
	}
	if strings.Contains(source, ";") && isparambegin {
		isparamend = true
	}

	return isparambegin, isparamend
}

//获取java类的包名
func getjavapack(source string) string {
	if strings.Contains(source, "package") {
		source = strings.Replace(source, "package", "", 1)
		source = strings.Replace(source, ";", "", 1)
		source = strings.TrimSpace(source)
		return source
	} else {
		return ""
	}
}

//从文件中读取执行方法的字符串，可处理执行方法写在多行中
func getfuncexecstr(reader *bufio.Reader) (execstr string) {
	isexecdefbegin := false
	isexecdefend := false

	var execdef []string

	for {
		str, err := reader.ReadString('\n') //按行读取，值赋予给str
		if err == io.EOF {
			break
		}
		if err != nil {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("java source file read err.")
			break
		}

		isexecdefbegin, isexecdefend = isexecdef(str, isexecdefbegin)

		if isexecdefbegin {
			execdef = append(execdef, strings.TrimSpace(str))
		}
		if isexecdefbegin && isexecdefend {
			break
		}
	}

	execstr = strings.TrimSpace(strings.Join(execdef, " "))

	return execstr
}

//从文件中读取类定义的字符串，可处理类定义写在多行中
func getpackclsstr(javapath string, reader *bufio.Reader) (packstr string, clsstr string) {
	isclsdefbegin := false
	isclsdefend := false
	packstr = ""

	var classdef []string

	for {
		str, err := reader.ReadString('\n') //按行读取，值赋予给str
		if err == io.EOF {
			break
		}
		if err != nil {
			global.LOG.WithFields(logrus.Fields{
				"err":          err,
				"javafilepath": javapath,
			}).Error("java source file read err.")
			break
		}
		str = strings.TrimSpace(str)

		if packstr == "" {
			packstr = getjavapack(str)
		}

		isclsdefbegin, isclsdefend = isclassdef(str, isclsdefbegin)

		if isclsdefbegin {
			classdef = append(classdef, str)
		}
		if isclsdefbegin && isclsdefend {
			break
		}
	}

	clsstr = strings.TrimSpace(strings.Join(classdef, " "))

	return packstr, clsstr
}

//获取类的名称
func getclsname(javapath string) string {
	tmplst := strings.Split(javapath, "\\") //仅适用于win，linux可能存在问题
	clsname := strings.Replace(tmplst[len(tmplst)-1], ".java", "", 1)

	return clsname
}

//从类定义字符传中解析处集成的接口，支持多重继承
func getclsintf(clsstr string) (intflst []string, found bool) {
	_, after, found := strings.Cut(clsstr, "implements")

	if found {
		after = strings.Replace(after, "{", "", 1)
		intflsttmp := strings.Split(after, ",")
		for _, inttmp := range intflsttmp {
			if strings.Contains(inttmp, "<") {
				before, _, _ := strings.Cut(inttmp, "<")
				intflst = append(intflst, before)
			} else if strings.Contains(inttmp, ">") {
				continue
			} else {
				intflst = append(intflst, inttmp)
			}
		}
	}

	return intflst, found
}

//判断一个类定义是否为参数bean的定义
func isparambean(allParamCgMap map[string]interface{}, clsstr string) bool {

	for parambeanname := range allParamCgMap {
		if strings.Contains(clsstr, parambeanname) {
			return true
		}
	}
	return false
}

//获取参数bean中的所有成员字符串
func getparamstrlst(reader *bufio.Reader) []string {
	isparambegin := false
	isparamend := false

	var paramlst []string
	var paramitmlst []string

	for {
		str, err := reader.ReadString('\n') //按行读取，值赋予给str
		if err == io.EOF {
			break
		}
		if err != nil {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("java source file read err.")
			break
		}

		isparambegin, isparamend = isparamdef(str, isparambegin)

		if isparambegin {
			paramitmlst = append(paramitmlst, strings.TrimSpace(str))
		}
		if isparambegin && isparamend {
			paramlst = append(paramlst, strings.Join(paramitmlst, " "))
			paramitmlst = []string{}
			isparambegin = false
			isparamend = false
		}
	}

	return paramlst
}

//解析文件内容主方法
func parseAtomSvrSource(allParamCgMap map[string]interface{}, javapath string) (packstr string, clsname string, execstr string, paramlst []string, intflst []string, clsstr string) {
	file, err := os.Open(javapath)
	if err != nil {
		global.LOG.WithFields(logrus.Fields{
			"err":          err,
			"javafilepath": javapath,
		}).Error("open java source file err.")
	}

	defer file.Close()
	global.LOG.Debug(javapath)
	reader := bufio.NewReader(file)

	//获取类名
	clsname = getclsname(javapath)

	//获取原子服务信息
	packstr, clsstr = getpackclsstr(javapath, reader)

	//获取参数bean类信息
	if isparambean(allParamCgMap, clsstr) {
		paramlst = getparamstrlst(reader)
	} else {
		//获取类继承接口清单
		intflst, _ = getclsintf(clsstr)
		//获取执行方法使用bean
		execstr = getfuncexecstr(reader)
	}

	global.LOG.Infoln(packstr + clsname + clsstr)

	return packstr, clsname, execstr, paramlst, intflst, clsstr
}

//判断类是否继承自原子服务接口
func isAtomIntf(allCgMap map[string]interface{}, intflst []string) (ok bool, intf string) {

	for _, intf := range intflst {
		_, ok := allCgMap[strings.TrimSpace(intf)]
		if ok {
			return ok, strings.TrimSpace(intf)
		}
	}

	return false, ""
}

//创建原子服务表数据对象
func createAtomSvrDefine(packstr string, clsname string, cataid string) orm.AtomSvrDefine {
	var asd orm.AtomSvrDefine
	asd.Atomsvrid = uuidutil.GetUUID()
	asd.Asname = clsname
	asd.Asdesc = clsname
	asd.Catagoryid = cataid

	serv := getservicebinding(packstr, clsname)
	asd.Servicebindingid = serv.Serviceid

	return asd
}

//创建服务绑定表数据
func getservicebinding(packstr string, clsname string) orm.Service {
	serviceabsname := packstr + "." + clsname

	//	service, count := orm.GetServiceByName(serviceabsname)
	service, count := existAsv(serviceabsname, asvMap)
	if 0 == count {
		serv := orm.Service{
			Serviceid:      uuidutil.GetUUID(),
			Project:        "cpcpb",
			Serviceabsname: serviceabsname,
		}
		//orm.CreateService(serv)
		asvs = append(asvs, serv)
		asvMap[serviceabsname] = serv
		return serv
	}

	return service
}

func existAsv(name string, asvMap map[string]orm.Service) (service orm.Service, count int) {
	if _, ok := asvMap[name]; ok {
		return asvMap[name], 1
	}
	return orm.Service{}, 0
}

//创建参数表数据
func createparamter(name string, ptype string, optional string, clspath string) string {
	var parameter = make(map[string]interface{})

	parameter["name"] = name
	parameter["type"] = ptype
	parameter["optional"] = optional
	parameter["classPath"] = clspath

	//param, count := orm.GetParamByName(name)
	paramid, count := existParam(name, paramMap)
	if count == 0 {
		paramid = uuidutil.GetUUID()
		//id := dict.UpdDict(parameter)
		params = append(params, orm.Parameter{
			Parameterid: paramid,
			Name:        name,
			Type:        ptype,
			Optional:    optional,
			Classpath:   clspath,
		})
		paramMap[name] = paramid
	}
	updParams = append(updParams, &parameter)
	pprelaMap[paramid] = &parameter
	return paramid
}

func existParam(name string, paramMap map[string]string) (paramid string, count int) {
	if _, ok := paramMap[name]; ok {
		return paramMap[name], 1
	}
	return "", 0
}

//创建参数表数据
func createparamterrel(parentparamid string, subparamid string, reltype string, isbasetype string, relname string) {
	var pl orm.Paramrelation

	pl.Isbasetype = isbasetype
	pl.Parentparamid = parentparamid
	pl.Subparamid = subparamid
	pl.Reltype = reltype
	pl.Relname = relname

	// _, count := orm.GetParameterbyId(parentparamid, subparamid)
	// if count == 0 {
	// 	orm.AddParamrelation(&pl)
	// }
	count := existParamRela(parentparamid+subparamid, paramRelaMap)
	if count == 0 {
		paramRelaMap[parentparamid+subparamid] = pl
		paramRelas = append(paramRelas, pl)
	}
}

func existParamRela(name string, relaMap map[string]orm.Paramrelation) int {
	if _, ok := relaMap[name]; ok {
		return 1
	}
	return 0
}

// //获取原子服务、参数扫描结果列表
// func getatomsvrlst() (asdlstmap []map[string]interface{}, paramlstmap map[string][]string) {

// 	paramlstmap = make(map[string][]string)

// 	//获取所有原子服务类接口
// 	allAtomCgMap := orm.GetCgAllMap("2")
// 	//获取所有参数类接口
// 	allParamCgMap := orm.GetCgAllMap("3")

// 	for _, javapath := range resultJavaList {
// 		packstr, clsname, execstr, paramlst, intflst, clsstr := parseAtomSvrSource(allParamCgMap, javapath)

// 		if isparambean(allParamCgMap, clsstr) {
// 			paramid := createparamter(clsname, "Map", "true", packstr+"."+clsname)
// 			paramlstmap[clsname] = paramlst
// 			paramlstmap[clsname+"$%$id"] = []string{paramid}
// 		}
// 		if ok, intf := isAtomIntf(allAtomCgMap, intflst); ok {
// 			cataid := allAtomCgMap[intf].(orm.Catagory)
// 			asd := createAtomSvrDefine(packstr, clsname, cataid.Catagoryid)
// 			asdmap := make(map[string]interface{})

// 			asdmap["asd"] = asd
// 			asdmap["execstr"] = execstr
// 			asdlstmap = append(asdlstmap, asdmap)

// 			global.LOG.Debug(execstr)

// 			//orm.CreateAtomSvr(&asd)
// 		}
// 	}

// 	return asdlstmap, paramlstmap
// }

//获取原子服务、参数扫描结果列表
func getatomsvrlst() (asdlstmap []map[string]interface{}, paramlstmap map[string][]string) {

	paramlstmap = make(map[string][]string)

	//获取所有原子服务类接口
	allAtomCgMap := orm.GetCgAllMap("2")
	//获取所有参数类接口
	allParamCgMap := orm.GetCgAllMap("3")

	for _, javapath := range resultJavaList {
		packstr, clsname, execstr, paramlst, intflst, clsstr := parseAtomSvrSource(allParamCgMap, javapath)

		if isparambean(allParamCgMap, clsstr) {
			paramid := createparamter(clsname, "Map", "true", packstr+"."+clsname)
			paramlstmap[clsname] = paramlst
			paramlstmap[clsname+"$%$id"] = []string{paramid}
		}
		if ok, intf := isAtomIntf(allAtomCgMap, intflst); ok {
			cataid := allAtomCgMap[intf].(orm.Catagory)
			asd := createAtomSvrDefine(packstr, clsname, cataid.Catagoryid)
			asdmap := make(map[string]interface{})

			asdmap["asd"] = asd
			asdmap["execstr"] = execstr
			asdlstmap = append(asdlstmap, asdmap)

			global.LOG.Debug(execstr)

			//orm.CreateAtomSvr(&asd)
		}
	}

	return asdlstmap, paramlstmap
}

//解析单行bean参数字符串
func parseparamitem(itemstr string) (itemname string, ptMap map[string]string, ptStr string) {
	var itemtmpstr string
	ptMap = make(map[string]string)

	//清理无用信息
	itemtmpstr = strings.Replace(itemstr, ";", "", 1)
	itemtmpstr = strings.TrimSpace(strings.Replace(itemtmpstr, "private", "", 1))
	if strings.Contains(itemtmpstr, "=") {
		itemtmpstr, _, _ = strings.Cut(itemtmpstr, "=")
		itemtmpstr = strings.TrimSpace(itemtmpstr)
	}

	if strings.Contains(itemtmpstr, "//") {
		itemtmpstr, _, _ = strings.Cut(itemtmpstr, "//")
		itemtmpstr = strings.TrimSpace(itemtmpstr)
	}

	//根据空格分隔获取变量名称
	itemlst := strings.Split(itemtmpstr, " ")
	itemname = itemlst[len(itemlst)-1]
	global.LOG.Infoln(itemname)

	//截取变量名称，获取参数类型字符串
	itemtmpstr, _, _ = strings.Cut(itemtmpstr, itemname)
	itemtmpstr = strings.TrimSpace(itemtmpstr)

	//定义参数类型判断正则表达式
	isLstMap := regexp.MustCompile(`^List\s*<\s*Map\s*<`)
	isLst := regexp.MustCompile(`^List\s*<`)
	isMap := regexp.MustCompile(`^Map\s*<`)

	//判断参数类型
	if isLstMap.MatchString(itemtmpstr) {
		itemtmpstr = strings.Replace(itemtmpstr, "List", "", 1)
		itemtmpstr = strings.Replace(itemtmpstr, "Map", "", 1)
		itemtmpstr = strings.ReplaceAll(itemtmpstr, "<", "")
		itemtmpstr = strings.ReplaceAll(itemtmpstr, ">", "")

		itemptLst := strings.Split(itemtmpstr, ",")

		ptMap["lstmapkey"] = strings.TrimSpace(itemptLst[0])
		ptMap["lstmapval"] = strings.TrimSpace(itemptLst[1])

		ptStr = "List"
	} else if isMap.MatchString(itemtmpstr) {
		itemtmpstr = strings.Replace(itemtmpstr, "Map", "", 1)
		itemtmpstr = strings.ReplaceAll(itemtmpstr, "<", "")
		itemtmpstr = strings.ReplaceAll(itemtmpstr, ">", "")

		itemptLst := strings.Split(itemtmpstr, ",")

		ptMap["mapkey"] = strings.TrimSpace(itemptLst[0])
		ptMap["mapval"] = strings.TrimSpace(itemptLst[1])

		ptStr = "Map"
	} else if isLst.MatchString(itemtmpstr) {
		itemtmpstr = strings.Replace(itemtmpstr, "List", "", 1)
		itemtmpstr = strings.ReplaceAll(itemtmpstr, "<", "")
		itemtmpstr = strings.ReplaceAll(itemtmpstr, ">", "")

		ptMap["lst"] = strings.TrimSpace(itemtmpstr)

		ptStr = "List"
	} else {
		ptMap["sub"] = strings.TrimSpace(itemtmpstr)
		ptStr = "Sub"
	}

	return itemname, ptMap, ptStr
}

//创建param&paramrel实体数据
func crtparamandrel(paramlstmap map[string][]string, itemname string, ptMap map[string]string, ptStr string, parentname string) {

	if "LIST" == strings.ToUpper(ptStr) || "MAP" == strings.ToUpper(ptStr) {
		//创建param
		global.LOG.Info(stringutil.GetTitleStr(ptStr))
		paramid := createparamter(itemname, stringutil.GetTitleStr(ptStr), "0", ptStr)

		//创建与上层param关系
		parentid := paramlstmap[parentname+"$%$id"][0]
		createparamterrel(parentid, paramid, "sub", "1", "")

		//创建集合类型与子元素关系
		for lmk, lmv := range ptMap {
			if _, ok := paramlstmap[lmv]; ok {
				subid := paramlstmap[lmv+"$%$id"][0]
				createparamterrel(paramid, subid, lmk, "1", "")
			} else {
				createparamterrel(paramid, lmv, lmk, "0", "")
			}

		}

	}
	if "Sub" == ptStr {
		ptype := ptMap["sub"]
		var paramid string
		var isbasetp string
		relname := ""

		//非集合bean对象直接创建与上层关联关系
		if _, ok := paramlstmap[ptype]; ok {
			paramid = paramlstmap[ptype+"$%$id"][0]
			isbasetp = "1"
			relname = itemname
		} else { //非集合先创建param，再建立关联关系
			paramid = createparamter(itemname, ptype, "0", ptype)
			isbasetp = "0"
		}

		parentid := paramlstmap[parentname+"$%$id"][0]
		createparamterrel(parentid, paramid, "sub", isbasetp, relname)

	}
}

//解析bean参数列表
func parseparamlst(paramlstmap map[string][]string) {

	for bname, paramlst := range paramlstmap {
		if strings.Contains(bname, "$%$id") {
			continue
		}
		for _, paramitm := range paramlst {
			itemname, ptMap, ptStr := parseparamitem(paramitm)
			global.LOG.Infoln(itemname, ptMap, ptStr, bname)
			crtparamandrel(paramlstmap, itemname, ptMap, ptStr, bname)
		}
	}
}

//解析原子服务执行方法
func parseestrtoparam(execstr string) (inparamid string, outparamid string) {

	inparam := regexp.MustCompile(`InnerReqDTO<.+>\s`)
	outparam := regexp.MustCompile(`InnerRespDTO<.+>`)

	inparamstr := inparam.FindString(execstr)
	before, _, _ := strings.Cut(execstr, "doAtom")
	outparamstr := outparam.FindString(before)

	inparamstr = strings.Replace(inparamstr, "InnerReqDTO<", "", 1)
	inparamstr = strings.TrimSpace(strings.Replace(inparamstr, ">", "", 1))

	outparamstr = strings.Replace(outparamstr, "InnerRespDTO<", "", 1)
	outparamstr = strings.TrimSpace(strings.Replace(outparamstr, ">", "", 1))

	// inpar, count := orm.GetParamByName(inparamstr)
	// if count > 0 {
	// 	inparamid = inpar.Parameterid
	// }
	// outpar, count := orm.GetParamByName(outparamstr)
	// if count > 0 {
	// 	outparamid = outpar.Parameterid
	// }

	inpar, count := existParam(inparamstr, paramMap)
	if count > 0 {
		inparamid = inpar
	}
	outpar, count := existParam(outparamstr, paramMap)
	if count > 0 {
		outparamid = outpar
	}

	return inparamid, outparamid
}

//原子服务入库
func ormcrtatomsvrdef(asd orm.AtomSvrDefine) {
	// _, count := orm.GetAtomSvrDefbyName(asd.Asname)
	count := existActivity(asd.Asname, activityMap)

	if count == 0 {
		//orm.CreateAtomSvr(asd)
		activities = append(activities, asd)
		activityMap[asd.Asname] = asd
	}
}

func existActivity(name string, activityMap map[string]orm.AtomSvrDefine) int {
	if _, ok := activityMap[name]; ok {
		return 1
	}
	return 0
}

//创建原子服务定义
func crtatomsvrdef(asdlstmap []map[string]interface{}) {

	for _, asdmap := range asdlstmap {
		asd, _ := asdmap["asd"].(orm.AtomSvrDefine)
		execstr, _ := asdmap["execstr"].(string)

		if execstr != "" {
			inparamid, outparamid := parseestrtoparam(execstr)
			asd.Inputparamid = inparamid
			asd.Outputparamid = outparamid
		}

		ormcrtatomsvrdef(asd)

	}
}

//扫描源码，创建原子服务信息
func AtomParseByPath() {

	localPath := orm.GetLocalPath("00001")

	resultJavaList = []string{}
	resultJsonList = []string{}
	params = []orm.Parameter{}
	asvs = []orm.Service{}
	paramMap = map[string]string{}
	asvMap = map[string]orm.Service{}
	activities = []orm.AtomSvrDefine{}
	activityMap = map[string]orm.AtomSvrDefine{}
	paramRelas = []orm.Paramrelation{}
	paramRelaMap = map[string]orm.Paramrelation{}
	pprelaMap = map[string]*map[string]interface{}{}
	updParams = []*map[string]interface{}{}
	err := filepath.Walk(localPath.LocalPath, walkFunc)
	if err != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("java source search err.")
		panic(err)
	}

	asdlstmap, paramlstmap := getatomsvrlst()

	global.LOG.Infoln(asdlstmap)
	global.LOG.Infoln(paramlstmap)

	parseparamlst(paramlstmap)
	crtatomsvrdef(asdlstmap)

	if len(asvs) > 0 {
		err := orm.SaveAsvs(asvs)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("scan err, saveServices error.")
		}
	}

	if len(params) > 0 {
		err := orm.SaveParams(params)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("scan err, saveParams error.")
		}
	}
	if len(activities) > 0 {
		err := orm.SaveActivies(activities)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("scan err, saveActivies error.")
		}
	}

	if len(updParams) > 0 {
		err := dict.BatchUpdate(updParams)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("scan err, update dict error.")
		}
	}

	if len(paramRelas) > 0 {
		paramRelas = updateRelas(paramRelas, pprelaMap)
		err := orm.SaveParamRelas(paramRelas)
		if nil != err {
			global.LOG.WithFields(logrus.Fields{
				"err": err,
			}).Error("scan err, saveParamRelas error.")
		}
	}

}

func updateRelas(relas []orm.Paramrelation, pprelaMap map[string]*map[string]interface{}) []orm.Paramrelation {
	res := relas
	for _, i := range relas {
		pp := orm.Paramrelation{}
		pp.Parentparamid = (*pprelaMap[i.Parentparamid])["parameterid"].(string)
		if i.Reltype != "sub" && i.Isbasetype == "0" {
			pp.Subparamid = i.Subparamid
		} else {
			pp.Subparamid = (*pprelaMap[i.Subparamid])["parameterid"].(string)
		}

		//sub-子成员 lst-数组元素类型 mapkey-图键类型 mapval-图值类型 lstmapkey-数组图键类型 lstmapval-数组图值类型
		pp.Reltype = i.Reltype
		//是否基础类型 0-是 1-否（默认值）
		pp.Isbasetype = i.Isbasetype
		pp.Relname = i.Relname
		res = append(res, pp)
	}
	return res

}
